/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file           : main.c
  * @brief          : Main program body
  ******************************************************************************
  * @attention
  *
  * <h2><center>&copy; Copyright (c) 2020 STMicroelectronics.
  * All rights reserved.</center></h2>
  *
  * This software component is licensed by ST under BSD 3-Clause license,
  * the "License"; You may not use this file except in compliance with the
  * License. You may obtain a copy of the License at:
  *                        opensource.org/licenses/BSD-3-Clause
  *
  ******************************************************************************
  */
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "usart.h"
#include "gpio.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "usart3.h"
#include "uart4.h"
#include "wifi.h"
#include "los_sys.h"
#include "los_task.h"
#include "los_memory.h"
#include "los_mux.h"
#include "los_base.h"
#include "los_swtmr.h"
#include "los_hwi.h"
#include "los_queue.h"
#include "los_event.h"
#include "los_typedef.h"
#include "stm32f4xx.h"
#include "onenet_http.h"
#include "led.h"
#include "beep.h"
#include "key.h"
#include "node_http.h"
#include "nodeserver_task.h"

/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */

/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/

/* USER CODE BEGIN PV */

/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP */

/* USER CODE END PFP */

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
char r_flag = 0;//esp8266 status isOk flag 
char s_flag = 1;//not used, preserve
char *presult;

uint8_t R[100] = {0};//usart3_irq receive buff
uint16_t cnt = 0;//usart3_irq receive cnt
static UINT32 g_usart3_rececie_irq_idle_msgQueue;
extern UART_HandleTypeDef USART3_Handler; 
extern UART_HandleTypeDef UART4_Handler; 

/*互斥锁句柄ID*/ 
UINT32 g_doGetMux = -1;

void USART3_IRQHandler(void)
{
    UINT32 uwRet = 0;
    if (__HAL_UART_GET_FLAG(&USART3_Handler, UART_FLAG_RXNE)) {
        R[cnt++] = USART3->DR;//这里不要写printf 会影响数据接收
        R[cnt] = '\0';
    }

    else if (__HAL_UART_GET_FLAG(&USART3_Handler, UART_FLAG_IDLE)) {
        __HAL_UART_CLEAR_IDLEFLAG(&USART3_Handler);
        uwRet = LOS_QueueWrite(g_usart3_rececie_irq_idle_msgQueue, R, cnt+1, 0);//把消息发往上层处理
        cnt = 0;
        if(uwRet != LOS_OK)
        {
            u3_printf("send message failure,error:%x\n",uwRet);
        }
    }
}

//开发板周期性轮询onenet服务器
void onetnet_doGet_cycle_Task(void *arg)
{
    static char resp[2048];//用来接收onenet_doGet请求onenetserver后服务器返回的响应数据
    while (1)
    {
        if(r_flag == 1)
        {                                    
            //char resp[2048];放在这里会卡死找错找了一晚上,所以请用static关键字修饰
            esp8266_onenet_doGet(SWITCH_DEVICE_ID, (char *)resp, 5000);
            onenet_recive_msg_paser((char *)resp);
            LOS_TaskDelay(10*1000);//每隔4s向onenet服务器轮询一次数据 这里用http来模拟mqtt的机制，即开发板一直周期查询onenet,而客户端那边可以通过进入onenet的开发板后台管理页随时改变onenet对从开发板来的请求的响应数据
        }
    }
}

//in future, this task will be depressed
void *esp8266usart4_Receive_Handler_Task(void *arg)
{
    while(1)
    {	
        //之所以不放在main函数里面初始化，是因为WiFi_Init()里面用到了liteos的延时函数
        if(r_flag == 0){                                    //如果r_flag标志等于0，表示需要复位重置8266模块
            if(WiFi_Init()==0){                             //调用WiFi_Init函数，返回0表示复位重置成功
                u3_printf("esp8266 init ok\r\n"); 
                r_flag = 1;                                 //r_flag标志置位，表示8266状态正常
            }
        }

        //if(Usart2_RxCompleted==1)//如果标志Usart2_RxCompleted置位，表示接收到数据
        //{                                          
        //    Usart2_RxCompleted = 0;//清除Usart2_RxCompleted置位标志                                         
        //    u3_printf("esp8266_received_data:%s\r\n", &RXbuff[2]);

        //    //onenet接收报文解析
        //    onenet_recive_msg_paser();

        //    //nodeserver接收报文解析
        //    nodeserver_recive_msg_paser();

        //    if(WiFi_Close(50))//准备关闭连接，超时单位100ms，超时时间5s
        //    {                                  
        //        r_flag = s_flag = 0;//标志清除                             
        //        u3_printf("close connect failed, ready reset esp8266\r\n");      
        //    }
        //    else 
        //    {
        //        u3_printf("close connect ok\r\n");                   
        //        if(s_flag==2)
        //        {                                   
        //            s_flag = 1;
        //        }
        //    }	
        //}
    }
}

void *usart3_Receive_Handler_Task(void *arg)
{
    UINT32 uwReadbuf;
    UINT32 uwRet = 0;
    while (1)
    {
        uwRet = LOS_QueueRead(g_usart3_rececie_irq_idle_msgQueue, &uwReadbuf, 100, LOS_WAIT_FOREVER);
        if(uwRet != LOS_OK)
        {
            u3_printf("recv message failure,error:%x\n",uwRet);
            //break;
        }
        u3_printf("recv message:%s\n", (char *)uwReadbuf);
        usart3_receive_msg_handler((char *)uwReadbuf);
    }
}

int Example_create_task(void)
{
    UINT32 uwRet = 0;
    UINT32 uwTask1, uwTask2, uwTask3;
    TSK_INIT_PARAM_S stInitParam1;

    stInitParam1.pfnTaskEntry = esp8266usart4_Receive_Handler_Task;
    stInitParam1.usTaskPrio = 9;
    stInitParam1.uwStackSize = 0x400;
    stInitParam1.pcName = "sendQueue";
    
    /*创建互斥锁*/
    LOS_MuxCreate(&g_doGetMux);
    u3_printf("g_doGetMux created\r\n");

    uwRet = LOS_TaskCreate(&uwTask1, &stInitParam1);
    if(uwRet != LOS_OK)
    {
        u3_printf(" LOS_Task Create failed\r\n");
        return uwRet;
    }

    stInitParam1.pfnTaskEntry = usart3_Receive_Handler_Task;
    uwRet = LOS_TaskCreate(&uwTask2, &stInitParam1);
    if(uwRet != LOS_OK)
    {
        u3_printf(" LOS_Task Create failed\r\n");
        return uwRet;
    }

    stInitParam1.pfnTaskEntry = onetnet_doGet_cycle_Task;
    uwRet = LOS_TaskCreate(&uwTask3, &stInitParam1);
    if(uwRet != LOS_OK)
    {
        u3_printf(" LOS_Task Create failed\r\n");
        return uwRet;
    }

    uwRet = LOS_QueueCreate("queue", 5, &g_usart3_rececie_irq_idle_msgQueue, 0, 50);
    if(uwRet != LOS_OK)
    {
        u3_printf(" LOS_Task Create failed\r\n");
        return uwRet;
    }
}

/* USER CODE END 0 */

/**
 * @brief  The application entry point.
 * @retval int
 */
int main(void)
{
    /* USER CODE BEGIN 1 */
    UINT32 uwRet = LOS_OK;
    /* USER CODE END 1 */

    /* MCU Configuration--------------------------------------------------------*/

    /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
    HAL_Init();

    /* USER CODE BEGIN Init */

    /* USER CODE END Init */

    /* Configure the system clock */
    SystemClock_Config();

    /* USER CODE BEGIN SysInit */

    /* USER CODE END SysInit */

    /* Initialize all configured peripherals */
    MX_GPIO_Init();
    //MX_USART3_UART_Init();
    //MX_UART4_Init();
    /* USER CODE BEGIN 2 */
    drv_led_init();
    drv_beep_init();
    drv_key_init();

    usart3_init(9600);
    Usart4_Init(115200);

    //一定要使能 hal库并没有帮我们自动使能
    __HAL_UART_ENABLE_IT(&USART3_Handler, UART_IT_IDLE);
    __HAL_UART_ENABLE_IT(&UART4_Handler, UART_IT_IDLE);

    uwRet = LOS_KernelInit();
    if(uwRet != LOS_OK) {
        u3_printf("LOS_KernelInit failed\r\n");
        return LOS_NOK;
    }
    uwRet = Example_create_task();
    if(uwRet != LOS_OK) {
        u3_printf("Example_create_task failed\r\n");
        return LOS_NOK;
    }
    LOS_Start();
    /* USER CODE END 2 */

    /* Infinite loop */
    /* USER CODE BEGIN WHILE */
    /* USER CODE END 3 */
}

/**
 * @brief System Clock Configuration
 * @retval None
 */
void SystemClock_Config(void)
{
    RCC_OscInitTypeDef RCC_OscInitStruct = {0};
    RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

    /** Configure the main internal regulator output voltage
    */
    __HAL_RCC_PWR_CLK_ENABLE();
    __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
    /** Initializes the RCC Oscillators according to the specified parameters
     * in the RCC_OscInitTypeDef structure.
     */
    RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
    RCC_OscInitStruct.HSIState = RCC_HSI_ON;
    RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
    RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
    if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
    {
        Error_Handler();
    }
    /** Initializes the CPU, AHB and APB buses clocks
    */
    RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
        |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
    RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI;
    RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
    RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
    RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

    if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK)
    {
        Error_Handler();
    }
}

/* USER CODE BEGIN 4 */

/* USER CODE END 4 */

/**
 * @brief  This function is executed in case of error occurrence.
 * @retval None
 */
void Error_Handler(void)
{
    /* USER CODE BEGIN Error_Handler_Debug */
    /* User can add his own implementation to report the HAL error return state */

    /* USER CODE END Error_Handler_Debug */
}

#ifdef  USE_FULL_ASSERT
/**
 * @brief  Reports the name of the source file and the source line number
 *         where the assert_param error has occurred.
 * @param  file: pointer to the source file name
 * @param  line: assert_param error line source number
 * @retval None
 */
void assert_failed(uint8_t *file, uint32_t line)
{
    /* USER CODE BEGIN 6 */
    /* User can add his own implementation to report the file name and line number,
tex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
    /* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */

/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
